home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / Venus / SimpleWindow.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-26  |  8.5 KB  |  330 lines  |  [TEXT/ALFA]

  1. /*
  2.  ***********************************************************************
  3.  *
  4.  *
  5.  *                                Simple Window Class
  6.  *        
  7.  *
  8.  ***********************************************************************
  9.  */
  10.  
  11. #include "image.h"
  12. #include "window.h"
  13. #include <PictUtil.h>
  14.  
  15. /*
  16.  *----------------------------------------------------------------------
  17.  *                            Service functions
  18.  */
  19.  
  20.                                         // Getting a bounding rectangle of an image
  21. ScreenRect::ScreenRect(const IMAGE& image)
  22. {
  23.     top = 0;
  24.     bottom = top + image.q_nrows();
  25.     left = 0;
  26.     right = left + image.q_ncols();
  27. }
  28.  
  29.                                     // Create a rectangle of given height/width
  30.                                     // positioned at the origin
  31. ScreenRect::ScreenRect(const rowcol& heightwidth)
  32. {
  33.     left = top = 0;
  34.     bottom = heightwidth.row();
  35.     right  = heightwidth.col();
  36. }
  37.  
  38.                                     // Create a rectangle of given height/width
  39.                                     // positioned at a given point
  40. ScreenRect::ScreenRect(const rowcol& origin, const rowcol& heightwidth)
  41. {
  42.     top  = origin.row();
  43.     left = origin.col();
  44.     bottom = top+heightwidth.row();
  45.     right  = left+heightwidth.col();
  46. }
  47.  
  48.  
  49.                                     // Shifting a rectangle by the same amount
  50.                                     // in X and Y
  51. ScreenRect& ScreenRect::operator += (const int offset)
  52.     top += offset; bottom += offset; left += offset; right += offset;
  53.     return *this;
  54. }
  55.  
  56.  
  57.                                     // Print what rectangle is this
  58. void ScreenRect::print(const char * title) const
  59. {
  60.     message("Rectangle %s (%d,%d) - (%d,%d)",title,top,left,bottom,right);
  61. }
  62.  
  63.  
  64.  
  65.                                     // Used to "implicitly" convert from C to Pascal
  66.                                     // string
  67. Pstr::Pstr(const char * c_str)
  68. {
  69.     strncpy((char *)pas_string,c_str,sizeof(*this)-2);
  70.     CtoPstr((char *)pas_string);
  71. }
  72.  
  73. /*
  74.  *----------------------------------------------------------------------
  75.  *        A generic simple window that can be dragged around the screen
  76.  *                and closed by clicking a "go-away" button
  77.  * No other events are handled, redefine the event handler if necessary.
  78.  */
  79.  
  80.  
  81.                                     // Create a color window of the specified size and title
  82.                                     // Note, the upper left corner of 'rect' must
  83.                                     // NOT be (0,0)!
  84. ScreenWindow::ScreenWindow(ScreenRect rect, const char * title)
  85. {
  86.     const int window_offset = 100;        // Cannot be 0 or small!
  87.     this_window = NewCWindow(nil,rect += window_offset,(Pstr)title,
  88.                             TRUE,noGrowDocProc,
  89.                             (WindowPtr)(-1),TRUE,(long)this);
  90.     assert( this_window != 0 );
  91.     SetPort(this_window);
  92.     SelectWindow(this_window);
  93. }
  94.  
  95.                                     // Create a color window from a resource template
  96. ScreenWindow::ScreenWindow(const short resource_id)
  97. {
  98.     this_window = GetNewCWindow(resource_id,nil,(WindowPtr)(-1));
  99.     SetWRefCon(this_window,(long)this);
  100.     assert( this_window != 0 );
  101.     SetPort(this_window);
  102.     SelectWindow(this_window);
  103. }
  104.  
  105.  
  106.  
  107.                                     // Close the window and clean up the rubble
  108. ScreenWindow::~ScreenWindow(void)
  109. {
  110.     assert( this_window != 0 );
  111.     DisposeWindow(this_window);
  112.     this_window = 0;
  113. }
  114.  
  115.  
  116.                                     // Event handling loop. Returns only when the
  117.                                     // window is to be destroyed
  118. void ScreenWindow::handle(void)
  119. {
  120.     const long event_timeout = 20;
  121.     EventRecord    theEvent;
  122.  
  123.     for(;;)
  124.     {
  125.         if( !WaitNextEvent(everyEvent, &theEvent,event_timeout,nil) )
  126.           if( handle_null_event(theEvent.when) )
  127.             continue;
  128.           else
  129.             return;
  130.           switch (theEvent.what)
  131.         {
  132.           case mouseDown:
  133.             if( !handle_mouse_down(theEvent) )
  134.               return;                        // Window is to be closed (go-away buttin clicked)
  135.             break;
  136.             
  137.           case updateEvt:
  138.             if( this_window == (WindowPtr)theEvent.message )
  139.               update();
  140.             break;
  141.  
  142.           case keyDown:
  143.           case autoKey:
  144.             if( !handle_key_down(theEvent) )
  145.               return;                        // a "quit" key must've been pressed
  146.             break;
  147.                         
  148.           case activateEvt:
  149.             if( this_window == (WindowPtr)theEvent.message )
  150.               activate(theEvent.modifiers & 0x01);
  151.             break;
  152.         }  
  153.     }
  154.     
  155. }
  156.  
  157.                                 // Handle "mouse-down" events
  158.                                 // Returns FALSE if the user clicked within the
  159.                                 // go-away region of our window. Otherwise,
  160.                                 // returns TRUE
  161.                                 // Handles dragging if necessary and system clicks
  162. Boolean ScreenWindow::handle_mouse_down(const EventRecord& the_event)
  163. {
  164.     WindowPtr    wp;
  165.     short        windowPart = FindWindow (the_event.where, &wp);
  166.     
  167.     switch (windowPart)
  168.     {
  169.       case inSysWindow: 
  170.         SystemClick(&the_event, wp);
  171.         break;
  172.         
  173.       case inMenuBar:
  174.         break;
  175.  
  176.       case inContent:
  177.           break;
  178.           
  179.       case inDrag:
  180.           if (wp == this_window )
  181.             drag(the_event.where);
  182.           break;
  183.                       
  184.       case inGoAway:
  185.           return FALSE;
  186.     }
  187.     return TRUE;
  188. }
  189.  
  190.                                         // Handles key_down & auto_key events. Return FALSE
  191.                                         // if the window is to be closed down
  192. Boolean ScreenWindow::handle_key_down(const EventRecord& the_event)
  193. {
  194.     return FALSE;                        // Each key kills the application, sorry
  195. }
  196.  
  197.  
  198.                                         // Handles null events, when nothing happens for some
  199.                                         // time. Return FALSE when it's time to die
  200. Boolean ScreenWindow::handle_null_event(const long event_time)
  201. {
  202.     return TRUE;                            // Keep going
  203. }
  204.  
  205.                             // Private window parts
  206.                                     // Handle an update event - redraw the window
  207.                                     // A virtual function draw() is called to do
  208.                                     // the actual redrawing
  209. void ScreenWindow::update(void)
  210. {
  211.     GrafPtr    savePort;
  212.     
  213.     GetPort(&savePort);
  214.     SetPort(this_window);
  215.     BeginUpdate(this_window);
  216.     draw();
  217.     EndUpdate(this_window);
  218.     SetPort(savePort);
  219. }
  220.  
  221.                                     // Make the entire window being redrawn
  222. void ScreenWindow::refresh(void)
  223. {
  224. //    EraseRect(&this_window->portRect);
  225.     InvalRect(&this_window->portRect);            
  226. }
  227.  
  228.                                         // Handle an activate or deactivate event
  229. void ScreenWindow::activate (const Boolean go_active)
  230. {
  231.     if (go_active)
  232.       SetPort(this_window);
  233. }
  234.  
  235.  
  236. /*
  237.  *----------------------------------------------------------------------
  238.  *            A simple window with an offscreen window buffer
  239.  */
  240.  
  241.                                 // Allocate the buffer for the offscreen
  242.                                 // drawing and load CLUT (if clut_id != 0)
  243. OffScreenWindow::OffScreenWindow
  244.     (ScreenRect rect, const char * title, const short clut_id)
  245.     : ScreenWindow(rect,title), graf_world(nil)
  246. {
  247.     CTabHandle clut_handle = nil;
  248.     if( clut_id != 0 )
  249.     {                                // try to get a user CLUT with that resource id
  250.        clut_handle = GetCTable(clut_id);
  251.        assert( clut_handle != 0 );
  252.        SetWinColor(our_window(),(WinCTab**)clut_handle);
  253.     }
  254.     do_well( NewGWorld(&graf_world,8,rect,clut_handle,nil,0) );
  255.     assert( graf_world != (void *)0 );
  256.  
  257. //    if( clut_handle != nil )
  258. //      DisposCTable(clut_handle);        // CLUT has been copied, and can be disposed of now
  259.                                         // But careful! CLUT is associated with the window
  260.                                         // by SetWinColor(), so we don't dispose of it
  261.  
  262.                                         // Get hold of the offscreen pixmap
  263.     pixmap = GetGWorldPixMap(graf_world);        // and make sure it looks like
  264.     assert( pixmap != nil && *pixmap != nil );    // we can use it
  265.  
  266.     assert( (**pixmap).cmpCount == 1 );            // We have a color table index
  267.     assert( !PixMap32Bit(pixmap) );
  268.  
  269.     _height = abs((**pixmap).bounds.top - (**pixmap).bounds.bottom);
  270.     _width  = abs((**pixmap).bounds.right - (**pixmap).bounds.left);
  271.     _bytes_per_row = (**pixmap).rowBytes & 0x7fff;
  272.  
  273.     assert( _height > 0 && _height < 10000 );         // Just to play safe
  274.     assert( _width > 0 && _width <= _bytes_per_row );    
  275.  
  276.     activate_palette();                    // Activate palette for the window
  277. }
  278.  
  279.                                 // Dispose of the offscreen buffer
  280. OffScreenWindow::~OffScreenWindow(void)
  281. {
  282.     assert( graf_world != nil );
  283.     DisposeGWorld(graf_world);
  284.     graf_world = nil;
  285.     PaletteHandle window_palette = GetPalette(our_window());
  286.     if( window_palette != nil )                // dispose of our palette if was allocated
  287.     {
  288.         SetPalette(our_window(),nil,FALSE);
  289.         DisposePalette(window_palette);
  290.     }
  291.     pixmap = nil;
  292.     _height = _width = _bytes_per_row = 0;
  293. }
  294.  
  295.                                     // Make sure that the colors of our off-screen
  296.                                     // buffer would be displayed properly (or close enough)
  297.                                     // on screen
  298. void OffScreenWindow::activate_palette(void)
  299. {
  300.     CTabHandle window_ctab = (**pixmap).pmTable;
  301.     assert( window_ctab != nil && *window_ctab != nil );
  302.  
  303.     PaletteHandle palette = NewPalette((**window_ctab).ctSize,window_ctab,pmTolerant+pmExplicit,0);
  304.     assert( palette != nil );
  305.     SetPalette(our_window(),palette,TRUE);
  306.     do_well( QDError() );
  307.     ActivatePalette(our_window());    
  308.     do_well( QDError() );
  309. }
  310.  
  311.  
  312.                                 // Get a bounding rectangle for the window
  313. ScreenRect OffScreenWindow::q_bounds(void) const
  314. {
  315.     return (**pixmap).bounds;
  316. }
  317.  
  318.  
  319.                                     // Actual drawing - moving the picture from the
  320.                                     // offscreen grafworld to the onscreen one
  321. void OffScreenWindow::draw(void)
  322. {
  323.     assert( LockPixels(pixmap) );
  324.     Rect& pixmap_rect = (**pixmap).bounds;
  325.     CopyBits((const BitMap *)*pixmap, &thePort->portBits, &pixmap_rect, 
  326.              &our_window()->portRect, /*ditherCopy*/ srcCopy, nil);
  327.     UnlockPixels(pixmap);
  328. }
  329.